#include "raft/node.h"

namespace libraft {
RaftNode::RaftNode(Options& options) : options_(options), raft_(nullptr) {}

RaftNode::~RaftNode() { StopLoop(); }

std::shared_ptr<Raft> RaftNode::StartNode(const std::string &path) {
  bg_thread_.reset(new std::thread(std::bind(&RaftNode::StartLoop, this, path)));
  {
    std::unique_lock<std::mutex> lk(mutex_);
    while (raft_ == nullptr) {
      condition_.wait(lk);
    }
  }
  return raft_;
}

void RaftNode::StopLoop() {
  if (raft_ && bg_thread_->joinable()) {
    raft_->QuitInLoop();
    bg_thread_->join();
  }
}

void RaftNode::StartLoop(const std::string &path) {
  std::shared_ptr<Raft> raft(new Raft(options_));
  rocksdb::Status s = raft->Open(path);
  if (!s.ok()) {
    assert(s.ok());
  }

  {
    std::unique_lock<std::mutex> lk(mutex_);
    raft_ = raft;
    condition_.notify_one();
  }

  raft_->Run();
  raft_.reset();
}

}  // namespace libraft